<?php

namespace App\Http\Controllers;

use App\Exceptions\AppException;
use App\Exceptions\AuthException;
use App\Jobs\SendSms;
use App\Libs\Company\SheetTemplateHandler\Manager;
use App\Libs\Company\SheetTemplateHandler\Report\AbstractTemplate;
use App\Libs\Sms\Sms;
use App\Models\District;
use App\Models\SubTask;
use App\Models\SubTaskLog;
use App\Services\TaskService;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;

class SubTaskController extends Controller
{
    public function list(Request $request)
    {
        $request->validate([
            'name' => 'nullable|string|max:50',
            'status' => 'nullable|in:1,2,3,4,5,6,7',
            'page' => 'nullable|integer|min:1',
            'per_page' => 'nullable|integer',
        ]);

        $query = SubTask::select(['id', 'updated_at', 'task_id', 'status'])->with('task')->whereHas('task');
        if (!Auth::user()->hasAnyPermission(['sub-task-report', 'sub-task-review1', 'sub-task-review2'])) {
            throw new AuthException();
        }
        if (Auth::user()->district_id != District::CITY_ID) {
            $query->where('district_id', Auth::user()->district_id);
        }
        if ($request->name) {
            $query->whereHas('task', function ($q) use ($request) {
                $q->where('name', 'like', "%{$request->name}%");
            });
        }
        if ($request->status) {
            $query->where('status', $request->status);
        }
        $res = $query->orderBy('updated_at', 'desc')->paginate($request->per_page);
        Arr::map($res->items(), function ($v) {
            $v->setAppends(['report_log', 'review1_log']);
        });
        return responder()->success($res);
    }

    public function show(Request $request)
    {
        $request->validate([
            'id' => 'required|integer|exists:sub_tasks,id,deleted_at,NULL',
        ]);

        if (!Auth::user()->hasAnyPermission(['sub-task-report', 'sub-task-review1', 'sub-task-review2'])) {
            throw new AuthException();
        }
        $model = SubTask::with(['task.sheetTemplate', 'task.taskTemplate', 'logs.operator', 'district'])->find($request->id);
        if (Auth::user()->district_id != District::CITY_ID &&
            Auth::user()->district_id != $model->district_id) {
            throw new AuthException();
        }
        if (in_array($model->status, [SubTask::STATUS_INITIALIZED, SubTask::STATUS_REJECTION1])) {
            $model['report_template_data'] = Manager::createReportHandler($model->task->sheetTemplate, $model)->renderReport();
        }
        $model['next_operators'] = TaskService::nextOperators($model);
        return responder()->success($model);
    }

    public function reset(Request $request)
    {
        $request->validate([
            'id' => 'required|integer|exists:sub_tasks,id,deleted_at,NULL',
        ]);

        if (!Auth::user()->hasPermissionTo('sub-task-report')) {
            throw new AuthException();
        }
        $model = SubTask::find($request->id);
        if (Auth::user()->district_id != District::CITY_ID &&
            Auth::user()->district_id != $model->district_id) {
            throw new AuthException();
        }
        if (!in_array($model->status, [SubTask::STATUS_INITIALIZED, SubTask::STATUS_REJECTION1])) {
            throw new AppException('任务状态异常');
        }
        $model->data = null;
        $model->save();
        return responder()->success();
    }

    public function report(Request $request)
    {
        $request->validate([
            'id' => 'required|integer|exists:sub_tasks,id,deleted_at,NULL',
            'data' => 'array',
            'submit' => 'required|in:0,1',
        ]);

        if (!Auth::user()->hasPermissionTo('sub-task-report')) {
            throw new AuthException();
        }
        $data = $this->resolveData($request->data);
        $model = SubTask::find($request->id);

        $template = Manager::createReportHandler($model->task->sheetTemplate, $model);
        $result = $template->validateReport($data, $request->submit);
        if ($result !== true) {
            return responder()->error(423, json_encode($result, 256));
        }

        if (Auth::user()->district_id != District::CITY_ID &&
            Auth::user()->district_id != $model->district_id) {
            throw new AuthException();
        }

        if (!in_array($model->status, [SubTask::STATUS_INITIALIZED, SubTask::STATUS_REJECTION1])) {
            throw new AppException('任务状态异常');
        }

        if ($request->submit) {
            TaskService::logSubTask(Auth::user(), $model, SubTaskLog::OPERATION_REPORT);
            $model->status = SubTask::STATUS_WAIT_REVIEW1;
            $model->last_reminded_at = null;
        }
        $model->data = $data;
        $model->save();

        $phones = TaskService::nextOperatorPhones($model);
        SendSms::dispatch($phones, Sms::TMPL2, [TaskService::getSmsTmplTitle($model)]);

        return responder()->success();
    }

    /**
     * 处理富文本数据
     */
    private function resolveData($data)
    {
        foreach ($data['sheets']['sheet-01']['cellData'] as $k1 => $v1) {
            foreach ($v1 as $k2 => $v2) {

                if (isset($v2['p'])) {
                    if (!Str::endsWith($v2['p']['body']['dataStream'], "\r\n")) {
                        $v2['p']['body']['dataStream'] .= "\r\n";
                    }
                    $data['sheets']['sheet-01']['cellData'][$k1][$k2] = [];
                    $data['sheets']['sheet-01']['cellData'][$k1][$k2]['p'] = $v2['p'];
                    $data['sheets']['sheet-01']['cellData'][$k1][$k2]['v'] = trim($v2['p']['body']['dataStream'], "\r\n");
                    $data['sheets']['sheet-01']['cellData'][$k1][$k2]['s'] = isset($v2['s']) ? $v2['s'] : '';
                }
            }
        }

        return $data;
    }

    public function review1(Request $request)
    {
        $request->validate([
            'id' => 'required|integer|exists:sub_tasks,id,deleted_at,NULL',
            'result' => 'required|in:1,2',
            'comment' => 'nullable|string|max:200',
        ]);

        if (!Auth::user()->hasPermissionTo('sub-task-review1')) {
            throw new AuthException();
        }
        $model = SubTask::find($request->id);
        if (Auth::user()->district_id != District::CITY_ID &&
            Auth::user()->district_id != $model->district_id) {
            throw new AuthException();
        }
        if (!in_array($model->status, [SubTask::STATUS_WAIT_REVIEW1, SubTask::STATUS_REJECTION2])) {
            throw new AppException('任务状态异常');
        }
        if ($request->result == SubTask::REVIEW_RESULT_YES) {
            TaskService::logSubTask(Auth::user(), $model, SubTaskLog::OPERATION_REVIEW1, $request->comment);
            $model->status = SubTask::STATUS_WAIT_REVIEW2;
        } else {
            TaskService::logSubTask(Auth::user(), $model, SubTaskLog::OPERATION_REJECT1, $request->comment);
            $model->status = SubTask::STATUS_REJECTION1;
        }
        $model->save();

        if ($model->status = SubTask::STATUS_WAIT_REVIEW2) {
            $phones = TaskService::nextOperatorPhones($model);
            SendSms::dispatch($phones, Sms::TMPL3, [TaskService::getSmsTmplTitle($model)]);
        }

        return responder()->success();
    }

    public function review2(Request $request)
    {
        $request->validate([
            'id' => 'required|integer|exists:sub_tasks,id,deleted_at,NULL',
            'result' => 'required|in:1,2',
            'comment' => 'nullable|string|max:200',
        ]);

        if (!Auth::user()->hasPermissionTo('sub-task-review2')) {
            throw new AuthException();
        }
        $model = SubTask::find($request->id);
        if ($model->status != SubTask::STATUS_WAIT_REVIEW2) {
            throw new AppException('任务状态异常');
        }
        if ($request->result == SubTask::REVIEW_RESULT_YES) {
            TaskService::logSubTask(Auth::user(), $model, SubTaskLog::OPERATION_REVIEW2, $request->comment);
            TaskService::finishSubTask($model);
        } else {
            TaskService::logSubTask(Auth::user(), $model, SubTaskLog::OPERATION_REJECT2, $request->comment);
            $model->status = SubTask::STATUS_REJECTION2;
            $model->save();
        }

        return responder()->success();
    }

    public function export(Request $request)
    {
        $request->validate([
            'id' => 'required|integer|exists:sub_tasks,id,deleted_at,NULL',
        ]);
        if (!Auth::user()->hasAnyPermission(['sub-task-report', 'sub-task-review1', 'sub-task-review2'])) {
            throw new AuthException();
        }
        $model = SubTask::with(['task.sheetTemplate', 'task.taskTemplate', 'logs.operator', 'district'])->find($request->id);
        if (Auth::user()->district_id != District::CITY_ID &&
            Auth::user()->district_id != $model->district_id) {
            throw new AuthException();
        }
        if (is_null($model->data)) {
            throw new AppException('工单还未填报');
        }
        Manager::export($model->data, $model->task->name);
        exit;
    }

    public function updateForce(Request $request)
    {
        $request->validate([
            'id' => 'required|integer|exists:sub_tasks,id,deleted_at,NULL',
            'data' => 'required|array',
        ]);
        if (!Auth::user()->hasRole(1)) {
            throw new AuthException();
        }
        $model = SubTask::find($request->id);
        $model->data = $request->data;
        $model->save();
        return responder()->success();
    }
}
